package com.email.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.StringTokenizer;

import sun.misc.BASE64Encoder;

public class SmtpEmail {
	
	// 用户名/密码加密
	private BASE64Encoder encode = new BASE64Encoder();
	// 套接字对象
	private Socket socket;
	
	public SmtpEmail() {}
	
	/**
	 * 连接服务器
	 * @param emailMessage
	 */
	private void setSocket(EmailMessage emailMessage) {
		try {
			if(emailMessage.getServer() != null 
					&& !emailMessage.getServer().equals("")
					&& emailMessage.getPort() != 0) {
				this.socket = new Socket(emailMessage.getServer(),
						emailMessage.getPort());
			} else {
				throw new NullPointerException("连接参数错误！");
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			System.out.println("服务器连接成功！");
		}
	}
	
	/**
	 * 注册到服务器
	 * @param emailMessage
	 */
	private void registerServer(EmailMessage emailMessage) {
		int result;
		result = getResult(emailMessage);
		// 判断是否连接
		if(result != 220) {
			try {
				throw new IOException("服务器注册失败！");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		// 发送消息确认
		sendMessage("helo " + emailMessage.getServer(), emailMessage);
	}
	
	/**
	 * 发送消息
	 * @param message
	 * @param emailMessage
	 * @return
	 */
	private int sendMessage(String message, EmailMessage emailMessage) {
		try {
			emailMessage.getWriter().write(message);
			emailMessage.getWriter().newLine();
			emailMessage.getWriter().flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return getResult(emailMessage);
	}
	
	/**
	 * 用户登录连接
	 * @param emailMessage
	 */
	private void userLogin(EmailMessage emailMessage) {
		int result;
		result = sendMessage("auth login", emailMessage);
		if(result != 334) {
			try {
				throw new IOException("用户验证失败！");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		result = sendMessage(encode.encode(emailMessage.getUserName().getBytes()),
				emailMessage);
		if(result != 334) {
			try {
				throw new IOException("用户名错误！");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		result = sendMessage(encode.encode(emailMessage.getPassword().getBytes()),
				emailMessage);
		if(result != 235) {
			try {
				throw new IOException("密码错误！");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 发送收件人 发件人
	 * @param emailMessage
	 */
	private void setFromTo(EmailMessage emailMessage) {
		int result;
		result = sendMessage("mail from:<" + emailMessage.getFrom() + ">", emailMessage);
		if(result != 250) {
			try {
				throw new IOException("发件人不存在！");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		result = sendMessage("rcpt to:<" + emailMessage.getTo() + ">", emailMessage);
		if(result != 250) {
			try {
				throw new IOException("收件人不存在！");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 发送邮件内容
	 * @param emailMessage
	 */
	private void setEmailContent(EmailMessage emailMessage) {
		int result;
		result = sendMessage("data", emailMessage);
		if(result != 354) {
			try {
				throw new IOException("数据无法传送！");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		try {
			emailMessage.getWriter().write("From: " + emailMessage.getFrom());
			emailMessage.getWriter().newLine();
			emailMessage.getWriter().write("To: " + emailMessage.getTo());
			emailMessage.getWriter().newLine();
			emailMessage.getWriter().write("Subject: " + emailMessage.getSubject());
			emailMessage.getWriter().newLine();
			emailMessage.getWriter().write("Content-Type: text/html");
			emailMessage.getWriter().newLine();
			emailMessage.getWriter().newLine();
			emailMessage.getWriter().write(emailMessage.getContent());
			emailMessage.getWriter().newLine();
			
			result = sendMessage(".", emailMessage);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		if(result != 250) {
			try {
				throw new IOException("邮件发送失败！");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 退出
	 * @param emailMessage
	 */
	private void quit(EmailMessage emailMessage) {
		int result;
		result = sendMessage("quit", emailMessage);
		if(result != 221) {
			try {
				throw new IOException("退出失败！");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 读取服务器返回消息状态
	 * @param emailMessage
	 * @return
	 */
	private int getResult(EmailMessage emailMessage) {
		int result;
		String readLine = "";
		try {
			// 读取服务器返回消息
			readLine = emailMessage.getReader().readLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 读取服务器返回消息状态码 转换为整数
		StringTokenizer tokenizer = new StringTokenizer(readLine, " ");
		result = Integer.parseInt(tokenizer.nextToken());
		// 返回
		return result;
	}
	
	/**
	 * 邮件发送
	 * @param emailMessage
	 */
	public void sendEmail(EmailMessage emailMessage){
		setSocket(emailMessage);
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(this.socket.getOutputStream()));
			emailMessage.setReader(reader);
			emailMessage.setWriter(writer);
			registerServer(emailMessage);
			userLogin(emailMessage);
			setFromTo(emailMessage);
			setEmailContent(emailMessage);
			quit(emailMessage);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			System.out.println("邮件发送成功！\n请查收！");
		}
	}
}
